package com.atguigu.yygh.hosp.service.impl;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.yygh.hosp.repository.ScheduleRepository;
import com.atguigu.yygh.hosp.service.DepartmentService;
import com.atguigu.yygh.hosp.service.HospitalService;
import com.atguigu.yygh.hosp.service.ScheduleService;
import com.atguigu.yygh.model.hosp.Schedule;
import com.atguigu.yygh.vo.hosp.BookingScheduleRuleVo;
import com.atguigu.yygh.vo.hosp.ScheduleQueryVo;

@Service
public class ScheduleServiceImpl implements ScheduleService{

	@Autowired
	private ScheduleRepository scheduleRepository;
	
	@Autowired
	private MongoTemplate mongoTemplate;
	
	@Autowired
	private HospitalService hospitalService;
	
	@Autowired
	private DepartmentService departmentService;

	@Override
	public void save(Map<String, Object> paramMap) {
		// TODO Auto-generated method stub
		// map 集合转换成对象    先转换成字符串
		String json = JSONObject.toJSONString(paramMap);
		//转换成 Schedule 对象
		Schedule schedule = JSONObject.parseObject(json,Schedule.class);
		String hosScheduleId = schedule.getHosScheduleId();
		String hostcode = schedule.getHostcode();
		//根据医院编号 科室编号 查询
		Schedule scheduleExit = scheduleRepository.getScheduleByHostcodeAndHosScheduleId(hostcode,hosScheduleId);
		if(scheduleExit != null){
			//存在   修改操作
			schedule.setUpdateTime(new Date());
			schedule.setIsDeleted(0);
			schedule.setStatus(1);
			scheduleRepository.save(schedule);
		}else{
			//不存在  添加操作
			schedule.setCreateTime(new Date());
			schedule.setUpdateTime(new Date());
			schedule.setIsDeleted(0);
			schedule.setStatus(1);
			scheduleRepository.save(schedule);
		}
		
	}

	@Override
	public Page<Schedule> findSchedulePage(int page, int limit, ScheduleQueryVo scheduleQueryVo) {
		//创建 pageable 对象  设置当前页  每页记录数
		Pageable pageable = PageRequest.of(page - 1, limit);
		//创建 Example<T> 对象 
		ExampleMatcher marExampleMatcher = ExampleMatcher.matching()
			.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING).withIgnoreCase(true);
		Schedule schedule = new Schedule();
		BeanUtils.copyProperties(scheduleQueryVo, schedule);
		schedule.setIsDeleted(0);
		schedule.setStatus(1);
		Example<Schedule> example = Example.of(schedule,marExampleMatcher);
		//分页
		Page<Schedule> scList = scheduleRepository.findAll(example, pageable);
		return scList;
	}

	@Override
	public void remove(String hostcode, String hosScheduleId) {
		// TODO Auto-generated method stub
		Schedule scheduleExit = scheduleRepository.getScheduleByHostcodeAndHosScheduleId(hostcode,hosScheduleId);
		//存在  获取id值 进行删除
		if(scheduleExit != null){
			scheduleRepository.deleteById(scheduleExit.getId());
		}
		//不存在   不需要删除
	}

	//查询排班规则数据
	@SuppressWarnings("deprecation")
	@Override
	public Map<String, Object> getRule(Integer page, Integer limit, String hostcode, String depcode) {
		//1.根据医院编号  科室编号进行查询
		Criteria criteria = Criteria.where("hostcode").is(hostcode).and("depcode").is(depcode);
		//2.根据工作日期进行分组 workData
		Aggregation agg = Aggregation.newAggregation(
				Aggregation.match(criteria), //匹配条件
				Aggregation.group("workDate") //分组字段
				.first("workDate").as("workDate") 
				//3.统计  预约号数量
				.count().as("docCount")
				.sum("reservedNumber").as("reservedNumber")
				.sum("availableNumber").as("availableNumber"),
				//排序
				Aggregation.sort(Sort.Direction.DESC,"workDate"),
				//4.分页操作  构建部分 
				Aggregation.skip((page-1) * limit),
				Aggregation.limit(limit)
		);
		//调用方法  执行
		AggregationResults<BookingScheduleRuleVo> aggRules = mongoTemplate.aggregate(agg, Schedule.class, BookingScheduleRuleVo.class);
		List<BookingScheduleRuleVo> booking = aggRules.getMappedResults();
		//分组查询之后 总记录数
		Aggregation aggCount = Aggregation.newAggregation(
				Aggregation.match(criteria), //匹配条件
				Aggregation.group("workDate") //分组字段
	    );
		AggregationResults<BookingScheduleRuleVo> aggTotal = mongoTemplate.aggregate(aggCount, Schedule.class, BookingScheduleRuleVo.class);
        int total = aggTotal.getMappedResults().size();
        //存储 只有日期  要求显示周几     
        //把日期对应的 周几 显示出来
        for(BookingScheduleRuleVo bs : booking){
        	Date workDate = bs.getWorkDate();
        	String week= getWeekOfDate(workDate);
        	bs.setDayOfWeek(week);
        }
        //设置 最终数据   进行返回
		Map<String, Object> map = new HashMap<>();
		map.put("booking", booking);
		map.put("total", total);
		
		//获取医院的名称
		String hostName = hospitalService.getHostName(hostcode);
		//其他基础数据
		Map<String, Object> mapName = new HashMap<>();
		mapName.put("hostname", hostName);
		map.put("mapName", mapName);
		return map;
	}
	
	/**
	 * 根据日期获取周几数据
	 *  @param date
	 */
	public String getWeekOfDate(Date date) {
	   
	    String[] weekDays = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
	    Calendar cal = Calendar.getInstance();
	    cal.setTime(date);
	    int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
	    if (w < 0)
	        w = 0;
	    return weekDays[w];
	}

	/**
	 * 根据医院编号   科室编号 工作日期   查询排班详细信息
     */
	@Override
	public List<Schedule> getDetailList(String hostcode, String depcode, String workDate) {
		// TODO Auto-generated method stub
		//根据条件   查询相应 LIST集合数据
		List<Schedule> scheduleList = scheduleRepository.getScheduleByHostcodeAndDepcodeAndWorkDate(hostcode, depcode, new DateTime(workDate).toDate());
		//list 集合进行遍历   param 里添加设置其他信息   医院名称   科室名称   日期对应周几
		scheduleList.stream().forEach(item ->{
			//调用方法   对集合操作
			this.packageSchedule(item);
		});
		return scheduleList;
	}

	//封装排班详情   其他信息 医院名称   科室名称   日期对应周几
	private void packageSchedule(Schedule schedule) {
		//设置医院名称  
		schedule.getParam().put("hostname", hospitalService.getHostName(schedule.getHostcode()));
		//设置科室名称
		schedule.getParam().put("depname",departmentService.getDepName(schedule.getHostcode(), schedule.getDepcode()));
		//设置日期对应周几
		schedule.getParam().put("dayOfWeek", this.getWeekOfDate(schedule.getWorkDate()));
	}
	
}
